package com.example.core;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import com.google.common.base.Joiner;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.Resource;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author liheng
 * @ClassName Tools
 * @Description wendang https://blog.csdn.net/hgffhh/article/details/83583841
 * @date 2021-07-28 17:37
 */
@Slf4j
public class Tools {

    /**
     * 日期格式化
     */
    public static final String DATE_NUMBER_PATTERN = "yyyy-MM-dd";


    /**
     * 获取时间字符串，格式：yyyyMMdd
     */
    public static String getDate() {
        return getFormatString(DATE_NUMBER_PATTERN);
    }

    /**
     * 返回pattern格式的字符串
     *
     * @param pattern
     * @return
     */
    private static String getFormatString(String pattern) {
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        return sdf.format(date);
    }

    /**
     * 字符串转换unicode
     *
     * @param string
     * @return
     */
    public static String string2Unicode(String string) {
        StringBuffer unicode = new StringBuffer();
        for (int i = 0; i < string.length(); i++) {
            // 取出每一个字符
            char c = string.charAt(i);
            // 转换为unicode
            unicode.append("\\u" + Integer.toHexString(c));
        }

        return unicode.toString();
    }

    /**
     * 含有unicode 的字符串转一般字符串
     *
     * @param unicodeStr 混有 Unicode 的字符串
     * @return
     */
    public static String unicodeStr2String(String unicodeStr) {
        int length = unicodeStr.length();
        int count = 0;
        //正则匹配条件，可匹配“\\u”1到4位，一般是4位可直接使用 String regex = "\\\\u[a-f0-9A-F]{4}";
        String regex = "\\\\u[a-f0-9A-F]{1,4}";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(unicodeStr);
        StringBuffer sb = new StringBuffer();

        while (matcher.find()) {
            String oldChar = matcher.group();//原本的Unicode字符
            String newChar = unicode2String(oldChar);//转换为普通字符
            // int index = unicodeStr.indexOf(oldChar);
            // 在遇见重复出现的unicode代码的时候会造成从源字符串获取非unicode编码字符的时候截取索引越界等
            int index = matcher.start();

            sb.append(unicodeStr.substring(count, index));//添加前面不是unicode的字符
            sb.append(newChar);//添加转换后的字符
            count = index + oldChar.length();//统计下标移动的位置
        }
        sb.append(unicodeStr.substring(count, length));//添加末尾不是Unicode的字符
        return sb.toString();
    }

    /**
     * unicode 转字符串
     *
     * @param unicode 全为 Unicode 的字符串
     * @return
     */
    public static String unicode2String(String unicode) {
        StringBuffer string = new StringBuffer();
        String[] hex = unicode.split("\\\\u");

        for (int i = 1; i < hex.length; i++) {
            // 转换出每一个代码点
            int data = Integer.parseInt(hex[i], 16);
            // 追加成string
            string.append((char) data);
        }

        return string.toString();
    }


    /**
     * 位置改变
     *
     * @param names
     * @param newSpecials
     * @return
     */
    public static Map<String, String> positionChange(List<String> names, List<String> newSpecials) {
        Random random = new Random();
        List<String> randoms = new ArrayList<>(names.size()+newSpecials.size());
        int len = names.size()+newSpecials.size();
        for (int i = 0; i < len; i++) {
            boolean flag = random.nextBoolean();
            if (flag) {
                if (names.size() != 0) {
                    randoms.add(names.get(0));
                    names.remove(0);
                } else {
                    randoms.add(newSpecials.get(0));
                    newSpecials.remove(0);
                }
            } else {
                if (newSpecials.size() != 0) {
                    randoms.add(newSpecials.get(0));
                    newSpecials.remove(0);
                } else {
                    randoms.add(names.get(0));
                    names.remove(0);
                }
            }
        }
        String unicode = Joiner.on("").join(randoms);
        String s1 = Tools.unicode2String(unicode);
        Map<String, String> map = new HashMap<>(2);
        map.put("unicode", unicode);
        map.put("value", s1);
        return map;
    }

    /**
     * 随机取出元素
     *
     * @param list
     * @param count 个数
     * @return
     */
    public static List<String> getStringByRadom(List<String> list, int count) {
        List backList = new ArrayList<String>();
        Random random = new Random();
        int backSum = count;
        if (count == 0) {
            return new ArrayList<>();
        }
        for (int i = 0; i < backSum; i++) {
            // 随机数的范围为0-list.size()-1
            int target = random.nextInt(list.size());
            backList.add(list.get(target));
        }
        return backList;
    }


    /**
     * @param filePath Excel文件路径
     * @param clazz    对应封装的数据实例对象
     * @return 返回数据集合
     */
    public static <E> List<E> readExcel(String filePath, Class<E> clazz) {
        // 定义输入流
        FileInputStream fis = null;
        List<E> datas = null;
        try {
            // 创建输入流对象
            fis = new FileInputStream(filePath);
            // 创建一个easypoi使用的配置类
            ImportParams params = new ImportParams();
            params.setTitleRows(0);
            // 读取数据
            datas = ExcelImportUtil.importExcel(fis, clazz, params);
        } catch (Exception e) {
            throw new RuntimeException("读取excel数据失败");
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return datas;
    }

    /**
     * 随机生成[startInclusive,endExclusive)之间的数字
     *
     * @param startInclusive 起始数，包含
     * @param endExclusive   终止数，包含
     * @return 随机数
     */
    public static int nextIntBh(final int startInclusive, final int endExclusive) {
        return new Random().nextInt(endExclusive - startInclusive + 1) + startInclusive;
    }

    /**
     * 判断是否在允许范围内的后缀
     *
     * @param ext
     * @return
     */
    public static boolean checkExt(String allowExt, String ext) {
        if (ext.length() == 0) {
            return false;
        }
        String[] params = allowExt.split("\\|");
        for (int i = 0; i < params.length; i++) {
            if (params[i].toLowerCase().equals(ext.toLowerCase())) {
                return true;
            }
        }
        return false;
    }

    /**
     * 读取文件
     *
     * @param resource
     * @return
     */
    public static String readJsonData(Resource resource) {
        BufferedReader br;
        String defaultString = null;
        try {
            br = new BufferedReader(new InputStreamReader(resource.getInputStream()));
            StringBuffer message = new StringBuffer();
            String line;
            while ((line = br.readLine()) != null) {
                message.append(line);
            }
            defaultString = message.toString();
            br.close();
        } catch (IOException e) {
            log.error("读取json文件失败：{}", e.getMessage());
        }
        return defaultString;
    }

    /**
     * 将特殊字符串转list
     *
     * @param str
     * @return
     */
    public static List<String> specials2List(String str) {
        String unicodeStrs = string2Unicode(str);
        unicodeStrs = unicodeStrs
                .replaceAll("\\\\u", "\\\\u0020\\\\u")
                .replaceFirst("\\\\u0020", "");
        List<String> specials = Arrays.asList(unicodeStrs.split("\\\\u0020"));
        return specials;
    }


    /**
     * 产生0,1的所有组合
     * http://www.cocoachina.com/articles/91961
     * @param dataArr 数组
     * @param index
     */
    public static  List<String> zeroOneGen(int[] dataArr, int index,List<String> results) {
        /**
         * 只输出 0 1组合
         */
        if (index == dataArr.length) {
            String str = "";
            for (int i = 0; i < dataArr.length; i++) {
                str = str + dataArr[i];
            }
            // System.out.println(str);
            results.add(str);
        }else {
            for (int i = 0; i < 2; i++) {
                dataArr[index] = i;
                zeroOneGen(dataArr,  index + 1,results);
            }
        }
        return results;
    }
}
